#include <iostream>
#include <string>
#include <limits>
#include <ctime>
#include <random>

// Generate a random number between min and max (inclusive)
// Assumes std::srand() has already been called
// Assumes max - min <= RAND_MAX
int getRandomNumber(int min, int max)
{
    static constexpr double fraction { 1.0 / (RAND_MAX + 1.0) };  // static used for efficiency, so we only calculate this value once
    // evenly distribute the random number across our range
    return min + static_cast<int>((max - min + 1) * (std::rand() * fraction));
}

namespace MyRandom {
    std::mt19937 mersenne{ static_cast<std::mt19937::result_type>(std::time(nullptr)) };
}

int getRandomNumber2(int min, int max)
{
    std::uniform_int_distribution<> die{ min, max };
    return die(MyRandom::mersenne);
}

int main()
{
//    std::string myName{ "Chen" };
//    std::cout << myName << '\n';

//    std::cout << "Enter your name: ";
//    std::string name{};
//    std::getline(std::cin, name);
//    std::cout << "Your name is " << name << '\n';

//    std::cout << "Pick 1 or 2: ";
//    int choice{};
//    std::cin >> choice;

//    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

//    std::cout << "Now enter your name: ";
//    std::string name{};
//    std::getline(std::cin, name);

//    std::cout << "Hello, " << name << ", you picked " << choice << '\n';

    std::string a{ "45" };
    std::string b{ "11" };

    std::cout << a + b << '\n'; // a and b will be concatenated
    a += " volts";
    std::cout << a << '\n';

    std::string myName{ "Alex" };
    std::cout << myName << " has " << myName.length() << " characters\n";

    // 8.4
//    enum class Color
//    {
//        red,
//        blue
//    };
//    enum class Fruit
//    {
//        banana,
//        apple
//    };

//    Color color{ Color::red };
//    Fruit fruit{ Fruit::banana };

//    if(color == fruit) // compile error here, as the compiler doesn't know how to compare different types Color and Fruit
//        std::cout << "color and fruit are equal\n";
//    else
//        std::cout << "color and fruit are not equal\n";

    // 8.5
    // 没有构造函数 无法使用初始化列表？
//    struct Employee
//    {
//        int id{ 0 };
//        int age{ 0 };
//        double wage{ 0.0 };
//    };

//    Employee joe{ 1, 32, 23.0 };
//    std::cout << joe.id << " " << joe.age << " " << joe.wage << '\n';

    struct Rectangle
    {
        Rectangle(double a, double b){
            length = a;
            width = b;
        }
        double length{ 1.0 };
        double width{ 1.0 };
    };
    Rectangle x{ 2.0, 2.0};
    std::cout << "x.length " << x.length << '\n';

    // 8.6 随机数
    std::srand(static_cast<unsigned int>(std::time(nullptr)));

    for(int count{ 1 }; count <= 10; ++count)
    {
        std::cout << getRandomNumber(1, 6) << '\t';
        if(count % 5 == 0)
            std::cout << '\n';
    }

    // 使用Mersenne Twister获得更好的随机数
    std::mt19937 mersenne{ static_cast<std::mt19937::result_type>(std::time(nullptr)) };
    std::uniform_int_distribution<> die{1, 6};
    for(int count{ 1 }; count <= 10; ++count)
    {
        std::cout << die(mersenne) << '\t';
        if(count % 5 == 0)
            std::cout << '\n';
    }

    std::cout << getRandomNumber2(1, 6) << '\t';
    std::cout << getRandomNumber2(6, 12) << '\t';

    return 0;
}

